package com.neusoft.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

/**
 * HttpClient 请求类
 * 
 * @author zhaocheng
 */
public class HttpClientUtil {

	private final static Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);
	
	private static PoolingHttpClientConnectionManager cm;

	private static String EMPTY_STR = "";

	private static String UTF_8 = "UTF-8";
	
	private static String APPLICATION_JSON = "application/json";
	
	private static String CONTENT_TYPE = "Content-Type";
	
	private static void init() {
		if(null == cm) {
			  LayeredConnectionSocketFactory factory = null;
		 	   try {
		 	      factory = new SSLConnectionSocketFactory(SSLContext.getDefault());
		 	   } catch (NoSuchAlgorithmException e) {
		 		  LOGGER.error("连接池初始化失败",e);
		 	   }
		 	   Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
		 	         .register("https", factory)
		 	         .register("http", new PlainConnectionSocketFactory())
		 	         .build();
		 	   cm =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
		}
	}

	/**
	 * 通过连接池获取HttpClient
	 * 
	 * @return
	 */
	private static CloseableHttpClient getHttpClient() {
		init();
		return HttpClients.custom().setConnectionManager(cm).build();
	}

	/**
	 * Http Get请求，无参数
	 * 
	 * @param url
	 * @return
	 */
	public static String httpGetRequest(String url) {
		HttpGet httpGet = new HttpGet(url);
		return getResult(httpGet);
	}

	/**
	 * Http Get请求，带参数
	 * 
	 * @param url
	 * @param params
	 * @return
	 * @throws URISyntaxException
	 */
	public static String httpGetRequest(String url, Map<String, Object> params) throws URISyntaxException {
		URIBuilder ub = new URIBuilder();
		ub.setPath(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		return getResult(httpGet);
	}

	/**
	 * Http Get请求，带头部，带参数
	 * 
	 * @param url
	 * @param headers
	 * @param params
	 * @return
	 * @throws URISyntaxException
	 */
	public static String httpGetRequest(String url, Map<String, Object> headers, Map<String, Object> params) throws URISyntaxException {
		URIBuilder ub = new URIBuilder();
		ub.setPath(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}
		return getResult(httpGet);
	}

	/**
	 * Http Post请求
	 * 
	 * @param url
	 * @return
	 */
	public static String httpPostRequest(String url) {
		HttpPost httpPost = new HttpPost(url);

		return getResult(httpPost);
	}

	public static String httpPostRequest(String url, Map<String, Object> params) throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

		return getResult(httpPost);
	}

	public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params) throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);

		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

		return getResult(httpPost);
	}
	
	public static JSONObject httpPostRequest(String url, String json) throws Exception {
		// 将JSON进行UTF-8编码,以便传输中文
		String encoderJson = URLEncoder.encode(json, UTF_8);

		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader(CONTENT_TYPE, APPLICATION_JSON);

		StringEntity se = new StringEntity(json);
		se.setContentType(APPLICATION_JSON);
		se.setContentEncoding(new BasicHeader(CONTENT_TYPE, APPLICATION_JSON));
		httpPost.setEntity(se);

		String result = getResult(httpPost);
		return JSONObject.parseObject(result);
	}
	
	public static String httpPostRequestStr(String url, String json) throws Exception {
		// 将JSON进行UTF-8编码,以便传输中文
		String encoderJson = URLEncoder.encode(json, UTF_8);

		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader(CONTENT_TYPE, APPLICATION_JSON);

		StringEntity se = new StringEntity(json);
		se.setContentType(APPLICATION_JSON);
		se.setContentEncoding(new BasicHeader(CONTENT_TYPE, APPLICATION_JSON));
		httpPost.setEntity(se);

		String result = getResult(httpPost);
		return result;
	}
	
	public static String httpPostRequestStrByToken(String url, String json,String token) throws Exception {
		
		// 将JSON进行UTF-8编码,以便传输中文
		String encoderJson = URLEncoder.encode(json, UTF_8);
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader(CONTENT_TYPE, APPLICATION_JSON);
		httpPost.addHeader("token",token);
		StringEntity se = new StringEntity(json,UTF_8);
		se.setContentType(APPLICATION_JSON);
		se.setContentEncoding(new BasicHeader(CONTENT_TYPE, APPLICATION_JSON));
		httpPost.setEntity(se);

		String result = getResult(httpPost);
		return result;
	}

//	/**
//	 * 文件上传
//	 * 
//	 * @param url
//	 * @param multipartFile
//	 * @return
//	 * @throws IOException
//	 */
//	public static String fileUpload(String url, MultipartFile multipartFile) throws IOException {
//		// CloseableHttpClient httpClient = HttpClients.createDefault();
//
//		String fileName = multipartFile.getOriginalFilename();
//		InputStream in = multipartFile.getInputStream();
//
//		MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//		builder.addBinaryBody("file", in, ContentType.MULTIPART_FORM_DATA, fileName);
//		builder.addTextBody("filename", fileName);
//
//		HttpPost httpPost = new HttpPost(url);
//		HttpEntity httpEntity = builder.build();
//		httpPost.setEntity(httpEntity);
//
//		return getResult(httpPost, in);
//	}

	/**
	 * 构建请求参数
	 * 
	 * @param params
	 * @return
	 */
	private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
		ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
		for (Map.Entry<String, Object> param : params.entrySet()) {
			pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
		}

		return pairs;
	}

	/**
	 * 处理Http请求
	 * 
	 * @param request
	 * @return
	 */
	private static String getResult(HttpRequestBase request) {
		// CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpClient httpClient = getHttpClient();
		try {
			CloseableHttpResponse response = httpClient.execute(request);
			// response.getStatusLine().getStatusCode();
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				// long len = entity.getContentLength();// -1 表示长度未知
				String result = EntityUtils.toString(entity);
				response.close();
				// httpClient.close();
				return result;
			}
		} catch (ClientProtocolException e) {
			LOGGER.error("getResult ClientProtocolException", e);
		} catch (IOException e) {
			LOGGER.error("getResult IOException", e);
		} finally {

		}

		return EMPTY_STR;
	}

	/**
	 * 处理Http请求
	 * 
	 * @param request
	 * @return
	 */
	private static String getResult(HttpRequestBase request, InputStream in) {
		// CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpClient httpClient = getHttpClient();
		try {
			CloseableHttpResponse response = httpClient.execute(request);
			// response.getStatusLine().getStatusCode();
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				// long len = entity.getContentLength();// -1 表示长度未知
				String result = EntityUtils.toString(entity);
				response.close();
				// httpClient.close();
				return result;
			}
		} catch (ClientProtocolException e) {
			LOGGER.error("getResult ClientProtocolException", e);
		} catch (IOException e) {
			LOGGER.error("getResult IOException", e);
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException e) {
				LOGGER.error("getResult IOException", e);
			}

		}

		return EMPTY_STR;
	}

}